package com.atguigu.config;

import com.atguigu.bean.Color;
import com.atguigu.bean.ColorFactoryBean;
import com.atguigu.bean.Person;
import com.atguigu.bean.Red;
import com.atguigu.conditional.LinuxConditional;
import com.atguigu.conditional.MyImportBeanDefinitionRegistrar;
import com.atguigu.conditional.MyImportSelector;
import com.atguigu.conditional.WindowsConditional;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

/**
 * @author : wenchao.long
 * @date : Created in 2020/11/14 09:49:03 周六
 * @description :
 *         <p>
 *         给容器中注册组件
 *         1) 包扫描 + 组件标注注解(@Controller/@Service/@Repository/@Component)[局限于自己写的]
 *         2) @Bean【导入第三方包里面的组件】
 *         3) @Import【快速给容器中导入一个组件】
 *         <p>
 *         1) @Import(要导入到容器中的组件) 容器中就会自动注册这个主键 id默认是全类名
 *         2) ImportSelector: 返回需要导入的组件的全类名数组
 *         3) ImportBeanDefinitionRegistrar: 手动注册bean到容器中
 *         </p>
 *         4) 使用Spring提供的FactoryBean(工厂Bean)
 *         默认获取到的是工厂bean调用getObject创建的对象
 *         要获取工厂bean本身，我们需要给id前面加上&
 *         &colorFactoryBean
 *         </p>
 * @see org.springframework.context.annotation.Import
 *         <p>
 *         导入组件，id默认是组件的类名 容器中就会自动注册这个组件
 *         </p>
 * @see org.springframework.context.annotation.ImportSelector
 *         <p>
 *         返回需要导入的组件的全类名数组
 *         </p>
 */
@Configuration
@Import({Color.class, Red.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class SpringConfig2 {

    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }

    /**
     * @return Person
     * @see org.springframework.context.annotation.Scope
     *         <p>
     *         默认是单实例的
     *         `ConfigurableBeanFactory.SCOPE_SINGLETON`        单实例
     *         `ConfigurableBeanFactory.SCOPE_PROTOTYPE`        多实例
     *         `REQUEST`    同一次请求创建一个实例
     *         `SESSION`    同一个session创建一个实例
     *         在单实例情况下: IOC容器启动就会创建对象
     *         在多实例情况下: 使用时，IOC容器才会创建对象
     *         </p>
     * @see org.springframework.context.annotation.Lazy
     *         <p>
     *         针对的是单实例，所以如果他的@Scope是多实例，则没有用
     *         容器启动不创建对象，第一次使用(获取)Bean创建对象，并初始化
     *         但是还是单实例
     *         </p>
     */
    @Bean
    public Person person() {
        System.out.println("创建对象----");
        return new Person("张三", 25);
    }

    /**
     * @return Person
     * @see org.springframework.context.annotation.Conditional
     *         <p>
     *         按照一定条件进行判断，满足条件给容器中注册bean
     *         如果是windows系统，给容器中注册("bill")
     *         如果是linux系统，给容器注册("linux")
     *         </p>
     */
    @Bean("bill")
    @Conditional(value = {WindowsConditional.class})
    public Person person01() {
        return new Person("Bill Gates", 64);
    }

    @Bean("linux")
    @Conditional(value = {LinuxConditional.class})
    public Person person02() {
        return new Person("linux", 48);
    }

}
